package org.infodavid.common.services;

import java.util.List;

import javax.persistence.PersistenceException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.infodavid.common.dto.IUserGroupListItem;
import org.infodavid.common.dto.IUserGroupListItem.EUserRole;
import org.infodavid.common.impl.services.validators.DefaultUserGroupValidator;
import org.infodavid.common.model.IUserGroup;
import org.infodavid.common.model.ModelFactory;
import org.infodavid.common.model.criteria.IExtendedSearchCriteria;
import org.infodavid.common.model.criteria.IUserGroupCriteria;
import org.infodavid.common.persistence.IQueryParameter;
import org.infodavid.common.reflect.InstantiationHelper;
import org.infodavid.common.services.exceptions.ServiceException;

/**
 * The Class GroupService.
 */
public abstract class UserGroupService extends
    AbstractEntityService<IUserGroupListItem,IUserGroup,IUserGroupCriteria> {

	/** The Constant ADMINISTRATORS. */
	public static final String ADMINISTRATORS = "administrators";

	/** The Constant MANAGERS. */
	public static final String MANAGERS = "managers";

	/** The Constant OPERATORS. */
	public static final String OPERATORS = "operators";

	/** The Constant SYSTEM. */
	public static final String SYSTEM = "system";

	/** The Constant USERS. */
	public static final String USERS = "users";

	/** The Constant GUEST. */
	public static final String GUEST = "guest";

	/** The Constant TRUSTED. */
	public static final String TRUSTED = "trusted";

	/** The Constant NOBODY. */
	public static final String NOBODY = "nobody";

	/** The singleton. */
	private static final UserGroupService SINGLETON;

	/** The Constant log. */
	private static final Log LOGGER = LogFactory.getLog(UserGroupService.class);

	static {
		try {
			SINGLETON = InstantiationHelper.getInstance().newInstance(UserGroupService.class);
		}
		catch (final Exception e) {
			LOGGER.fatal("Can not instantiate the " + UserGroupService.class.getName(), e);

			throw new Error(e);
		}
	}

	/**
	 * returns the singleton.
	 * @return <code>GroupService</code>
	 */
	public static UserGroupService getInstance() {
		return SINGLETON;
	}

	/**
	 * Instantiates a new service.
	 */
	protected UserGroupService() {
		super(IUserGroup.class, new DefaultUserGroupValidator(), ModelFactory.getInstance().getBuilder(
		    IUserGroup.class));
	}

	/**
	 * Find the entity by name.
	 * @param value the name
	 * @param context the context
	 * @return the entity
	 * @throws ServiceException the service exception
	 * @throws PersistenceException the persistence exception
	 */
	public abstract IUserGroup findByName(IApplicationContext context, String value)
	    throws ServiceException, PersistenceException;

	/**
	 * Find the entity by the member.
	 * @param value the user identifier
	 * @param context the context
	 * @param results the entities
	 * @param parameters the parameters
	 * @return the number of results
	 * @throws ServiceException the service exception
	 * @throws PersistenceException the persistence exception
	 */
	public abstract long findByMember(IApplicationContext context, long value,
	    List<IUserGroupListItem> results, List<IQueryParameter> parameters) throws ServiceException,
	    PersistenceException;

	/**
	 * Checks if the given user is member of the specified group.
	 * @param user the user identifier
	 * @param group the group identifier
	 * @param context the context
	 * @return true, if user is a member of the group
	 * @throws PersistenceException the persistence exception
	 * @throws ServiceException the service exception
	 */
	public abstract boolean isMemberOf(IApplicationContext context, long user, long group)
	    throws PersistenceException, ServiceException;

	/**
	 * Checks if the given user is member of the specified group.
	 * @param user the user name
	 * @param group the group name
	 * @param context the context
	 * @return true, if user is a member of the group
	 * @throws PersistenceException the persistence exception
	 * @throws ServiceException the service exception
	 */
	public abstract boolean isMemberOf(IApplicationContext context, String user, String group)
	    throws PersistenceException, ServiceException;

	/**
	 * Find by type.
	 * @param context the context
	 * @param role the role
	 * @param results the list of groups
	 * @param criteria the criteria
	 * @return the number of results
	 * @throws ServiceException the service exception
	 * @throws PersistenceException the persistence exception
	 */
	public abstract long findByRole(IApplicationContext context, EUserRole role,
	    List<IUserGroup> results, IExtendedSearchCriteria criteria) throws ServiceException,
	    PersistenceException;

	/**
	 * Find by guest flag.
	 * @param context the context
	 * @param type the type
	 * @param results the list of groups
	 * @param criteria the criteria
	 * @return the number of results
	 * @throws ServiceException the service exception
	 * @throws PersistenceException the persistence exception
	 */
	public abstract long findByGuest(IApplicationContext context, boolean flag,
	    List<IUserGroup> results, IExtendedSearchCriteria criteria) throws ServiceException,
	    PersistenceException;

	/**
	 * Adds the members.
	 * @param context the context
	 * @param groupKey the group key
	 * @param memebers the members
	 * @throws ServiceException the service exception
	 * @throws PersistenceException the persistence exception
	 */
	public abstract void addMembers(IApplicationContext context, long groupKey, long... members)
	    throws ServiceException, PersistenceException;

	/**
	 * Removes the members.
	 * @param context the context
	 * @param groupKey the group key
	 * @param memebers the members
	 * @throws ServiceException the service exception
	 * @throws PersistenceException the persistence exception
	 */
	public abstract void removeMembers(IApplicationContext context, long groupKey, long... members)
	    throws ServiceException, PersistenceException;
}
